package com.apache.design.controller;

import com.apache.api.vo.ResultMsg;
import com.apache.cache.service.impl.LoadCacheFactory;
import com.apache.cache.util.Validator;
import com.apache.design.template.BuildProjectFactory;
import com.apache.rpc.entity.RpcDatasource;
import com.apache.tools.FileZipUtil;
import com.apache.tools.StrUtil;
import com.apache.uct.common.ToolsUtil;
import net.sf.json.JSONObject;
import org.apache.log4j.Logger;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * 生成工程Action
 */
public class DesignAction extends HttpServlet {

	private Logger log = Logger.getLogger(getClass());
	private String localFileName = "config.properties";

	/**
	 * 参数说明
	 * doCode 调用方法，如：project
	 * sysEname 系统标识，如：test1
	 * serverPort 服务端口
	 * jdbcUrl 数据库URL
	 * databaseType 数库类型
	 * jdbcUsername 用户名
	 * jdbcPassword 密码
	 * driverClassName 驱动
	 */
	public void doGet(HttpServletRequest req, HttpServletResponse response) throws ServletException, IOException {
		this.doInvoke(req, response);
	}

	public void doPost(HttpServletRequest req, HttpServletResponse response) throws ServletException, IOException {
		this.doInvoke(req, response);
	}

	private void doInvoke(HttpServletRequest req, HttpServletResponse response) throws IOException {
		String sysEname = req.getParameter("sysEname");
		if (Validator.isNull(sysEname)) {
			ResultMsg msg =  new ResultMsg("F", "请选择需要生成工程的系统");
			outputJson(JSONObject.fromObject(msg).toString(),response,"");
			return ;
		}
		JSONObject json = null;
		String methodKey = StrUtil.doNull(req.getParameter("doCode"), "project");
		try {
			if("project".equalsIgnoreCase(methodKey)){
				Object obj = this.createProject(req,response);
				json = JSONObject.fromObject(obj);
			} else {
				Object obj = this.createInfos(req,response);
				json = JSONObject.fromObject(obj);
			}
		} catch (Exception e) {
			String serverName = sysEname+"-server";//工程名称
			log.error("执行方法[" + methodKey + "]时出错：", e);
			ResultMsg msg =  new ResultMsg("F", "工程["+serverName+"]创建失败");
			json = JSONObject.fromObject(msg);
		}
		outputJson(json.toString(),response,"");
	}

	/**
	 * 生成工程全部内容
	 */
	private Object createProject(HttpServletRequest req, HttpServletResponse response){
		ResultMsg msg = new ResultMsg("F","创建工程失败！");
		try {
			Map<String,String> param = getParameterMap(req);
			buildParam(req,param);
			if(StrUtil.isNull(param.get("jdbcUrl"))){
				return new ResultMsg("F","请先选择或创建数据源！");
			}
			String serverName = req.getParameter("sysEname")+"-server";//工程名称
			param.put("projectName",serverName);
			String fileUploadDirectory =  ToolsUtil.getInstance().getLocalByKey(localFileName, "UPLOAD_DIRECTORY");//获取文件需要上传到的根目录
			String path = fileUploadDirectory+"/project/";
			param.put("filePath",path);//存放地址
			System.out.println("filePath="+path);
			boolean mark = BuildProjectFactory.instance().ctreateProject(param);
			if(mark){
				String fileDownloadUrl =  ToolsUtil.getInstance().getLocalByKey(localFileName, "DOWNLOAD_URL");//获取文件需要下载的根目录地址
				String downRoot = fileDownloadUrl+"/project/";//下载地址

				log.info("工程["+serverName+"]创建成功，开始压缩文件...");
				String serverRootPath = path + serverName;
				String zipPath =serverRootPath + ".zip";
				Map<String,String> reultMap = FileZipUtil.fileToZip(serverRootPath,zipPath);
				log.info("对文件压缩的结果："+reultMap);
				String zipRootPath = reultMap.get("fileNameNew");
				log.info("压缩文件存放位置："+zipRootPath);
				String downLoadPath=downRoot+serverName+".zip";
				log.info("压缩文件下载地址："+downLoadPath);
				msg = new ResultMsg("T", downLoadPath);
			}
		} catch (IOException e) {
		}
		return msg;
	}

	/**
	 * 生成指定工程文件
	 */
	private Object createInfos(HttpServletRequest req, HttpServletResponse response){
		try {
			String methodKey = req.getParameter("doCode");
			Map<String,String> param = getParameterMap(req);
			String serverName = req.getParameter("sysEname")+"-server";//工程名称
			param.put("projectName",serverName);
			String fileUploadDirectory =  ToolsUtil.getInstance().getLocalByKey(localFileName, "UPLOAD_DIRECTORY");//获取文件需要上传到的根目录
			String path = fileUploadDirectory+"/project/";
			param.put("filePath",path);//存放地址
			boolean mark =false;
			buildParam(req,param);
			if(StrUtil.isNull(param.get("jdbcUrl"))){
				return new ResultMsg("F","请先选择或创建数据源！");
			}
			if("ibatis".equalsIgnoreCase(methodKey)){//生成工程ibatis配置
				mark = BuildProjectFactory.instance().ctreateMybtaits(param);
			} else if("spring".equalsIgnoreCase(methodKey)){//生成工程spring配置
				mark = BuildProjectFactory.instance().ctreateSpring(param);
			} else if("config".equalsIgnoreCase(methodKey)){//生成系统配置成功
				mark = BuildProjectFactory.instance().ctreateConfig(param);
			} else if("manager".equalsIgnoreCase(methodKey)){//生成dao,entity,manager相关类
				BuildProjectFactory.instance().ctreateEntity(param);
				BuildProjectFactory.instance().ctreateDao(param);
				mark = BuildProjectFactory.instance().ctreateManager(param);
			} else if("action".equalsIgnoreCase(methodKey)){//生成请求action类
				mark = BuildProjectFactory.instance().ctreateAction(getParameterMap(req));
			}
			if(mark){
				String fileDownloadUrl =  ToolsUtil.getInstance().getLocalByKey(localFileName, "DOWNLOAD_URL");//获取文件需要下载的根目录地址
				String downRoot = fileDownloadUrl+"/project/";//下载地址
				log.info("工程["+serverName+"]创建成功，开始压缩文件...");
				String serverRootPath = path + serverName;
				String zipPath =serverRootPath + ".zip";
				Map<String,String> reultMap = FileZipUtil.fileToZip(serverRootPath,zipPath);
				log.info("对文件压缩的结果："+reultMap);
				String zipRootPath = reultMap.get("fileNameNew");
				log.info("压缩文件存放位置："+zipRootPath);
				String downLoadPath=downRoot+serverName+".zip";
				log.info("压缩文件下载地址："+downLoadPath);
				return new ResultMsg("T", downLoadPath);
			}
		} catch (IOException e) {

		}
		return new ResultMsg("T","生成xml成功");
	}

	/**
	 * 输出json数据
	 */
	private void outputJson(String json, HttpServletResponse response, String callback)
			throws IOException {
		if (StrUtil.isNotNull(json)) {
			PrintWriter out = response.getWriter();
			if (StrUtil.isNull(callback)) {
				response.setContentType("text/html;charset=UTF-8");
				response.setHeader("Access-Control-Allow-Origin", "*");
				response.setHeader("Access-Control-Allow-Methods", "POST,GET");
				response.setHeader("Access-Control-Allow-Credentials", "true");
				out.print(json);
			} else {
				response.setContentType("application/javascript");
				out.print(callback + "(" + json + ")");
			}
			out.flush();
			out.close();
		}
	}

	private void buildParam(HttpServletRequest req,Map<String,String> param){
		param.put("serverIp",StrUtil.doNull(param.get("serverIp"),"127.0.0.1"));
		param.put("serverPort",StrUtil.doNull(param.get("serverPort"),"8080"));
		param.put("socketPort",StrUtil.doNull(param.get("socketPort"),"8003"));
		param.put("ajpPort",param.get("socketPort").substring(0,2)+"19");
		if(StrUtil.isNull(param.get("jdbcUrl"))){
			String sysEname = req.getParameter("sysEname");
			Object obj = LoadCacheFactory.getInstance().getCacheManager("").getCacheObjectByKey("rpc_datasource_" +sysEname);
			if(obj != null) {
				RpcDatasource source = (RpcDatasource)obj;
				param.put("jdbcUrl",source.getJdbcUrl());
				param.put("databaseType", source.getDatabaseType());
				param.put("driverClassName", source.getDriverClassName());
				param.put("jdbcUsername", source.getJdbcUsername());
				param.put("jdbcPassword", source.getJdbcPassword());
			}
		}
	}
	/**
	 * description:  获取请求参数
	 */
	private Map<String, String> getParameterMap(HttpServletRequest request) throws IOException {
		Map<String, String> map = new HashMap<String, String>();
		Set keSet = request.getParameterMap().entrySet();
		for (Iterator itr = keSet.iterator(); itr.hasNext(); ) {
			Map.Entry me = (Map.Entry) itr.next();
			String ok = String.valueOf(me.getKey());
			Object ov = me.getValue();
			String value = "";
			if (ov instanceof String[]) {
				String[] vls = (String[]) ov;
					for (int i = 0; i < vls.length; i++) {////批量处理
						if (i == vls.length - 1) {
							value += StrUtil.doNull(vls[i], "_");
						} else {
							value += StrUtil.doNull(vls[i], "_") + "-#-";
						}
					}
			} else {
				value = String.valueOf(ov);
			}
			if (StrUtil.isNotNull(value)) {
				String str = new String(value.getBytes("iso8859-1"), "iso8859-1");
				if (value.equals(str)) {
					value = str;
				}
				map.put(ok, value);
			}
		}
		return map;
	}
}
